package com.kwdb.importtool.model;

import com.kwdb.importtool.core.DataValidator;
import lombok.Data;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * 迁移结果模型类
 * 记录迁移过程的详细结果和统计信息
 */
@Data
public class MigrationResult {
    // 基本信息
    private String migrationId;
    private Date startTime;
    private Date endTime;
    private boolean success;
    private String message;

    // 源文件信息
    private String sourceFile;
    private long sourceFileSize;
    private int sourceStatementCount;

    // 迁移统计
    private int totalStatements;
    private int processedStatements;
    private int successfulStatements;
    private int failedStatements;
    private int skippedStatements;

    // 性能指标
    private long totalDuration; // 毫秒
    private long parsingDuration;
    private long conversionDuration;
    private long executionDuration;
    private long validationDuration;
    private double statementsPerSecond;

    // 进度信息
    private String currentStep;
    private int progress; // 百分比 0-100
    private List<ProgressUpdate> progressHistory;

    // 错误和警告
    private List<MigrationError> errors;
    private List<MigrationWarning> warnings;

    // 详细结果
    private Map<SQLStatement.StatementType, StatementStatistics> statementStatistics;
    private List<TableMigrationResult> tableResults;
    private DataValidator.ValidationSummary validationSummary;

    // 系统信息
    private String kwdbVersion;
    private String toolVersion;
    private Map<String, String> systemProperties;

    public MigrationResult() {
        this.migrationId = generateMigrationId();
        this.startTime = new Date();
        this.progressHistory = new CopyOnWriteArrayList<>();
        this.errors = new CopyOnWriteArrayList<>();
        this.warnings = new CopyOnWriteArrayList<>();
        this.statementStatistics = new EnumMap<>(SQLStatement.StatementType.class);
        this.tableResults = new CopyOnWriteArrayList<>();
        this.systemProperties = new HashMap<>();

        // 初始化语句统计
        for (SQLStatement.StatementType type : SQLStatement.StatementType.values()) {
            statementStatistics.put(type, new StatementStatistics(type));
        }

        // 记录系统信息
        recordSystemInfo();

        // 设置默认值
        this.totalStatements = 0;
        this.processedStatements = 0;
        this.successfulStatements = 0;
        this.failedStatements = 0;
        this.skippedStatements = 0;
        this.progress = 0;
    }

    /**
     * 生成迁移ID
     */
    private String generateMigrationId() {
        return "MIG_" + System.currentTimeMillis() + "_" + UUID.randomUUID().toString().substring(0, 8);
    }

    /**
     * 记录系统信息
     */
    private void recordSystemInfo() {
        systemProperties.put("java.version", System.getProperty("java.version"));
        systemProperties.put("os.name", System.getProperty("os.name"));
        systemProperties.put("os.version", System.getProperty("os.version"));
        systemProperties.put("user.name", System.getProperty("user.name"));
        systemProperties.put("user.timezone", TimeZone.getDefault().getID());
    }

    /**
     * 添加进度更新
     */
    public void addProgressUpdate(String step, int progress) {
        ProgressUpdate update = new ProgressUpdate(step, progress, new Date());
        this.progressHistory.add(update);
        this.currentStep = step;
        this.progress = progress;
    }

    /**
     * 添加错误信息
     */
    public void addError(String errorMessage) {
        addError(errorMessage, null, null);
    }

    public void addError(String errorMessage, String sqlStatement) {
        addError(errorMessage, sqlStatement, null);
    }

    public void addError(String errorMessage, String sqlStatement, Exception exception) {
        MigrationError error = new MigrationError(errorMessage, sqlStatement, exception);
        this.errors.add(error);
        this.success = false;
    }

    /**
     * 添加警告信息
     */
    public void addWarning(String warningMessage) {
        addWarning(warningMessage, null);
    }

    public void addWarning(String warningMessage, String sqlStatement) {
        MigrationWarning warning = new MigrationWarning(warningMessage, sqlStatement);
        this.warnings.add(warning);
    }

    /**
     * 更新语句统计
     */
/*    public void updateStatementStatistics(SQLStatement statement, boolean success, long duration) {
        SQLStatement.StatementType type = statement.getStatementType();
        StatementStatistics stats = statementStatistics.get(type);

        if (stats != null) {
            stats.incrementProcessed();
            if (success) {
                stats.incrementSuccessful();
            } else {
                stats.incrementFailed();
            }
            stats.addDuration(duration);
        }

        this.processedStatements++;
        if (success) {
            this.successfulStatements++;
        } else {
            this.failedStatements++;
        }
    }*/

    /**
     * 添加表迁移结果
     */
/*    public void addTableResult(TableMigrationResult tableResult) {
        this.tableResults.add(tableResult);
    }*/

    /**
     * 计算总持续时间
     */
    public void calculateDurations() {
        if (startTime != null && endTime != null) {
            this.totalDuration = endTime.getTime() - startTime.getTime();

            // 计算每秒处理语句数
            if (totalDuration > 0) {
                this.statementsPerSecond = (double) processedStatements / (totalDuration / 1000.0);
            }
        }
    }

    /**
     * 完成迁移
     */
    public void complete(boolean success, String message) {
        this.endTime = new Date();
        this.success = success;
        this.message = message;
        calculateDurations();
    }

    /**
     * 获取成功率
     */
    public double getSuccessRate() {
        if (processedStatements == 0) return 0.0;
        return (double) successfulStatements / processedStatements * 100.0;
    }

    /**
     * 获取失败率
     */
    public double getFailureRate() {
        if (processedStatements == 0) return 0.0;
        return (double) failedStatements / processedStatements * 100.0;
    }

    /**
     * 是否有错误
     */
    public boolean hasErrors() {
        return !errors.isEmpty();
    }

    /**
     * 是否有警告
     */
    public boolean hasWarnings() {
        return !warnings.isEmpty();
    }

    /**
     * 获取错误数量
     */
    public int getErrorCount() {
        return errors.size();
    }

    /**
     * 获取警告数量
     */
    public int getWarningCount() {
        return warnings.size();
    }

    /**
     * 生成摘要报告
     */
    public SummaryReport generateSummaryReport() {
        SummaryReport report = new SummaryReport();
        report.setMigrationId(migrationId);
        report.setSuccess(success);
        report.setMessage(message);
        report.setTotalDuration(totalDuration);
        report.setTotalStatements(totalStatements);
        report.setProcessedStatements(processedStatements);
        report.setSuccessfulStatements(successfulStatements);
        report.setFailedStatements(failedStatements);
        report.setSuccessRate(getSuccessRate());
        report.setErrorCount(getErrorCount());
        report.setWarningCount(getWarningCount());

        return report;
    }

    /**
     * 生成详细报告
     */
    public DetailedReport generateDetailedReport() {
        DetailedReport report = new DetailedReport();
        report.setSummary(generateSummaryReport());
        report.setErrors(new ArrayList<>(errors));
        report.setWarnings(new ArrayList<>(warnings));
        report.setTableResults(new ArrayList<>(tableResults));
        report.setStatementStatistics(new HashMap<>(statementStatistics));
        report.setValidationSummary(validationSummary);

        return report;
    }

    /**
     * 进度更新记录
     */
    @Data
    public static class ProgressUpdate {
        private final String step;
        private final int progress;
        private final Date timestamp;

        public ProgressUpdate(String step, int progress, Date timestamp) {
            this.step = step;
            this.progress = progress;
            this.timestamp = timestamp;
        }
    }

    /**
     * 迁移错误
     */
    @Data
    public static class MigrationError {
        private String id;
        private String message;
        private String sqlStatement;
        private String exceptionType;
        private String exceptionMessage;
        private String stackTrace;
        private Date timestamp;
        private int lineNumber;

        public MigrationError(String message, String sqlStatement, Exception exception) {
            this.id = "ERR_" + UUID.randomUUID().toString().substring(0, 8);
            this.message = message;
            this.sqlStatement = sqlStatement;
            this.timestamp = new Date();

            if (exception != null) {
                this.exceptionType = exception.getClass().getSimpleName();
                this.exceptionMessage = exception.getMessage();

                StringWriter sw = new StringWriter();
                exception.printStackTrace(new PrintWriter(sw));
                this.stackTrace = sw.toString();
            }
        }

        public String getFormattedMessage() {
            StringBuilder sb = new StringBuilder();
            sb.append("[").append(timestamp).append("] ").append(message);

            if (sqlStatement != null) {
                sb.append("\nSQL: ").append(sqlStatement);
            }

            if (exceptionMessage != null) {
                sb.append("\nException: ").append(exceptionMessage);
            }

            return sb.toString();
        }
    }

    /**
     * 迁移警告
     */
    @Data
    public static class MigrationWarning {
        private String id;
        private String message;
        private String sqlStatement;
        private Date timestamp;
        private WarningLevel level;

        public MigrationWarning(String message, String sqlStatement) {
            this.id = "WARN_" + UUID.randomUUID().toString().substring(0, 8);
            this.message = message;
            this.sqlStatement = sqlStatement;
            this.timestamp = new Date();
            this.level = WarningLevel.WARNING;
        }

        public String getFormattedMessage() {
            return "[" + timestamp + "] " + message +
                    (sqlStatement != null ? "\nSQL: " + sqlStatement : "");
        }

        public enum WarningLevel {
            INFO, WARNING, ERROR
        }
    }

    /**
     * 语句统计信息
     */
    @Data
    public static class StatementStatistics {
        private SQLStatement.StatementType statementType;
        private int totalProcessed;
        private int successful;
        private int failed;
        private long totalDuration;
        private long minDuration = Long.MAX_VALUE;
        private long maxDuration = Long.MIN_VALUE;
        private double averageDuration;

        public StatementStatistics(SQLStatement.StatementType statementType) {
            this.statementType = statementType;
        }

        public void incrementProcessed() {
            totalProcessed++;
        }

        public void incrementSuccessful() {
            successful++;
        }

        public void incrementFailed() {
            failed++;
        }

        public void addDuration(long duration) {
            totalDuration += duration;
            minDuration = Math.min(minDuration, duration);
            maxDuration = Math.max(maxDuration, duration);

            if (totalProcessed > 0) {
                averageDuration = (double) totalDuration / totalProcessed;
            }
        }

        public double getSuccessRate() {
            if (totalProcessed == 0) return 0.0;
            return (double) successful / totalProcessed * 100.0;
        }
    }

    /**
     * 表迁移结果
     */
    @Data
    public static class TableMigrationResult {
        private String tableName;
        private boolean schemaCreated;
        private boolean dataImported;
        private boolean indexesCreated;
        private int expectedRowCount;
        private int actualRowCount;
        private long importDuration;
        private List<String> errors;
        private List<String> warnings;

        public TableMigrationResult(String tableName) {
            this.tableName = tableName;
            this.errors = new ArrayList<>();
            this.warnings = new ArrayList<>();
        }

        public void addError(String error) {
            this.errors.add(error);
        }

        public void addWarning(String warning) {
            this.warnings.add(warning);
        }

        public boolean isSuccess() {
            return errors.isEmpty() &&
                    (!schemaCreated || (dataImported && actualRowCount >= expectedRowCount));
        }
    }

    /**
     * 摘要报告
     */
    @Data
    public static class SummaryReport {
        private String migrationId;
        private boolean success;
        private String message;
        private long totalDuration;
        private int totalStatements;
        private int processedStatements;
        private int successfulStatements;
        private int failedStatements;
        private double successRate;
        private int errorCount;
        private int warningCount;

        public String toFormattedString() {
            return String.format(
                    "Migration Summary:\n" +
                            "ID: %s\n" +
                            "Status: %s\n" +
                            "Message: %s\n" +
                            "Duration: %d ms\n" +
                            "Statements: %d total, %d processed, %d successful, %d failed\n" +
                            "Success Rate: %.2f%%\n" +
                            "Errors: %d, Warnings: %d",
                    migrationId,
                    success ? "SUCCESS" : "FAILED",
                    message,
                    totalDuration,
                    totalStatements, processedStatements, successfulStatements, failedStatements,
                    successRate,
                    errorCount, warningCount
            );
        }
    }

    /**
     * 详细报告
     */
    @Data
    public static class DetailedReport {
        private SummaryReport summary;
        private List<MigrationError> errors;
        private List<MigrationWarning> warnings;
        private List<TableMigrationResult> tableResults;
        private Map<SQLStatement.StatementType, StatementStatistics> statementStatistics;
        private DataValidator.ValidationSummary validationSummary;

        public DetailedReport() {
            this.errors = new ArrayList<>();
            this.warnings = new ArrayList<>();
            this.tableResults = new ArrayList<>();
            this.statementStatistics = new HashMap<>();
        }
    }

    /**
     * 导出为JSON字符串
     */
    public String toJson() {
        // 简化版JSON序列化，实际项目中可以使用Jackson或Gson
        StringBuilder json = new StringBuilder();
        json.append("{\n");
        json.append("  \"migrationId\": \"").append(migrationId).append("\",\n");
        json.append("  \"success\": ").append(success).append(",\n");
        json.append("  \"message\": \"").append(escapeJson(message)).append("\",\n");
        json.append("  \"startTime\": \"").append(startTime).append("\",\n");
        json.append("  \"endTime\": \"").append(endTime).append("\",\n");
        json.append("  \"totalDuration\": ").append(totalDuration).append(",\n");
        json.append("  \"totalStatements\": ").append(totalStatements).append(",\n");
        json.append("  \"processedStatements\": ").append(processedStatements).append(",\n");
        json.append("  \"successfulStatements\": ").append(successfulStatements).append(",\n");
        json.append("  \"failedStatements\": ").append(failedStatements).append(",\n");
        json.append("  \"successRate\": ").append(String.format("%.2f", getSuccessRate())).append(",\n");
        json.append("  \"errorCount\": ").append(getErrorCount()).append(",\n");
        json.append("  \"warningCount\": ").append(getWarningCount()).append("\n");
        json.append("}");

        return json.toString();
    }

    private String escapeJson(String str) {
        if (str == null) return "";
        return str.replace("\"", "\\\"")
                .replace("\n", "\\n")
                .replace("\r", "\\r")
                .replace("\t", "\\t");
    }

    /**
     * 导出为HTML报告
     */
    public String toHtml() {
        // 简化版HTML报告
        return "<html><body><h1>Migration Report</h1><pre>" + toJson() + "</pre></body></html>";
    }
}